#ifndef SOBJC_PROTOCOL_H
#define SOBJC_PROTOCOL_H

#include <sobjc-commons/st.h>
#include <sobjc-commons/list.h>
#include <sobjc-commons/type.h>
#include "method_sig.h"
#include "node.h"

typedef struct objc_protocol            *objc_protocol_t;
typedef struct objc_protocol_method     *objc_protocol_method_t;

OBJC_SIMPLE_DEF_LIST(protocol_list, objc_protocol_t)

struct objc_protocol {
  char *name;
  BOOL has_def;
  objc_protocol_list_t protocols;
  st_table_t inst_meths;
  st_table_t class_meths;
};

struct objc_protocol_method {
  objc_protocol_t owner;
  objc_method_sig_t sig;
  BOOL optional;
  BOOL is_inst;
};

typedef void (*objc_protocol_iter_f)(objc_protocol_t, void *);

objc_protocol_t objc_make_protocol(const char *);
objc_protocol_method_t objc_make_protocol_method(objc_method_sig_t, BOOL, BOOL);

void objc_register_protocol(objc_protocol_t);
void objc_declare_protocol(const char *);
objc_protocol_t objc_get_protocol(const char *);
void objc_iter_protocols(objc_protocol_iter_f, void *);

objc_method_sig_t objc_protocol_register_method_sig(objc_protocol_t, const char *, objc_node_t, BOOL);
void objc_protocol_add_method(objc_protocol_t, objc_protocol_method_t, BOOL);
objc_protocol_method_t objc_protocol_get_method(objc_protocol_t, const char *, BOOL);
BOOL objc_protocol_conforms_protocol(objc_protocol_t, const char *);

#endif /* SOBJC_PROTOCOL_H */
